#include "viewarea.h"

#include <QLabel>
#include <QVBoxLayout>
#include <QShortcut>

#include "core/stitch.h"
#include "core/config.h"
#include "core/coreconfig.h"
#include "core/sessionconfig.h"
#include "mainwindow.h"
#include "core/event.h"
#include "utils/widgetutils.h"

using namespace stitch;

ViewArea::ViewArea(QWidget *p_parent)
    : QWidget(p_parent),
      NavigationMode(NavigationMode::Type::DoubleKeys, this)
{
    setupUI();

    setAcceptDrops(true);

    setupShortcuts();

    //    connect(this, &ViewArea::viewSplitsCountChanged,
    //            this, &ViewArea::handleViewSplitsCountChange);

    //    auto mainWindow = Stitch::getInst().getMainWindow();
    //    connect(mainWindow, &MainWindow::mainWindowClosed,
    //            this, [this](const QSharedPointer<Event> &p_event) {
    //                if (p_event->m_handled) {
    //                    return;
    //                }

    //                if (Config::getInst().getCoreConfig().isRecoverLastSessionOnStartEnabled()) {
    //                    saveSession();
    //                }

    //                bool ret = close(false);
    //                if (!ret) {
    //                    p_event->m_response = false;
    //                    p_event->m_handled = true;
    //                }
    //            });

    //    connect(mainWindow, &MainWindow::mainWindowClosedOnQuit,
    //            this, [this]() {
    //                close(true);
    //            });

    //    connect(mainWindow, &MainWindow::mainWindowStarted,
    //            this, &ViewArea::loadSession);

    //    connect(&Stitch::getInst(), &Stitch::nodeAboutToMove,
    //            this, &ViewArea::handleNodeChange);

    //    connect(&Stitch::getInst(), &Stitch::nodeAboutToRemove,
    //            this, &ViewArea::handleNodeChange);

    //    connect(&Stitch::getInst(), &Stitch::nodeAboutToRename,
    //            this, &ViewArea::handleNodeChange);

    //    connect(&Stitch::getInst(), &Stitch::nodeAboutToReload,
    //            this, &ViewArea::handleNodeChange);

    //    connect(&Stitch::getInst(), &Stitch::closeFileRequested,
    //            this, &ViewArea::closeFile);

    //    auto &Config = Config::getInst();
    //    connect(&Config, &Config::editorConfigChanged,
    //            this, [this]() {
    //                forEachViewWindow([](ViewWindow *p_win) {
    //                    p_win->handleEditorConfigChange();
    //                    return true;
    //                });

    //                const auto &markdownEditorConfig = Config::getInst().getEditorConfig().getMarkdownEditorConfig();
    //                PlantUmlHelper::getInst().update(markdownEditorConfig.getPlantUmlJar(),
    //                                                 markdownEditorConfig.getGraphvizExe(),
    //                                                 markdownEditorConfig.getPlantUmlCommand());
    //                GraphvizHelper::getInst().update(markdownEditorConfig.getGraphvizExe());
    //            });

    //    m_fileCheckTimer = new QTimer(this);
    //    m_fileCheckTimer->setSingleShot(false);
    //    m_fileCheckTimer->setInterval(2000);
    //    connect(m_fileCheckTimer, &QTimer::timeout,
    //            this, [this]() {
    //                auto win = getCurrentViewWindow();
    //                if (win) {
    //                    win->checkFileMissingOrChangedOutsidePeriodically();
    //                }
    //            });

    //    connect(qApp, &QApplication::focusChanged,
    //            this, [this](QWidget *p_old, QWidget *p_now) {
    //                if (!p_now) {
    //                    m_fileCheckTimer->stop();
    //                } else if (!p_old && m_currentSplit) {
    //                    m_fileCheckTimer->start();
    //                }
    //            });
}

ViewArea::~ViewArea()
{
    // All splits/workspaces/windows should be released during close() before destruction.
    //    Q_ASSERT(m_splits.isEmpty() && m_currentSplit == nullptr);
    //    Q_ASSERT(m_workspaces.isEmpty());
}

QSize ViewArea::sizeHint() const
{
    const QSize preferredSize(400, 300);
    auto sz = QWidget::sizeHint();
    if (sz.width() < preferredSize.width())
    {
        sz = preferredSize;
    }

    return sz;
}

QVector<void *> ViewArea::getVisibleNavigationItems()
{
    QVector<void *> items;
    m_navigationItems.clear();

    //    int idx = 0;
    //    for (auto split : m_splits) {
    //        if (split->getViewWindowCount() == 0) {
    //            continue;
    //        }
    //        if (idx >= NavigationMode::c_maxNumOfNavigationItems) {
    //            break;
    //        }
    //        auto info = split->getNavigationModeInfo();
    //        for (int i = 0; i < info.size() && idx < NavigationMode::c_maxNumOfNavigationItems; ++i, ++idx) {
    //            items.push_back(info[i].m_viewWindow);
    //            m_navigationItems.push_back(info[i]);
    //        }
    //    }
    return items;
}

void ViewArea::placeNavigationLabel(int p_idx, void *p_item, QLabel *p_label)
{
    Q_UNUSED(p_item);
    Q_ASSERT(p_idx > -1);
    //    p_label->setParent(m_navigationItems[p_idx].m_viewWindow->getViewSplit());
    //    p_label->move(m_navigationItems[p_idx].m_topLeft);
}

void ViewArea::handleTargetHit(void *p_item)
{
    //    if (p_item) {
    //        setCurrentViewWindow(static_cast<ViewWindow *>(p_item));
    //        focus();
    //    }
}

void ViewArea::clearNavigation()
{
    NavigationMode::clearNavigation();

    m_navigationItems.clear();
}

void ViewArea::dragEnterEvent(QDragEnterEvent *p_event)
{
}

void ViewArea::dropEvent(QDropEvent *p_event)
{
}

void ViewArea::setupUI()
{
    setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);

    m_mainLayout = new QVBoxLayout(this);
    m_mainLayout->setContentsMargins(0, 0, 0, 0);
}

void ViewArea::setupShortcuts()
{
    //const auto &coreConfig = Config::getInst().getCoreConfig();

    // CloseTab.
    //    {
    //        auto shortcut = WidgetUtils::createShortcut(coreConfig.getShortcut(CoreConfig::CloseTab), this);
    //        if (shortcut) {
    //            connect(shortcut, &QShortcut::activated,
    //                    this, [this]() {
    //                        auto win = getCurrentViewWindow();
    //                        if (win) {
    //                            closeViewWindow(win, false, true);
    //                        }
    //                    });
    //        }
    //    }

    //    // LocateNode.
    //    {
    //        auto shortcut = WidgetUtils::createShortcut(coreConfig.getShortcut(CoreConfig::LocateNode), this);
    //        if (shortcut) {
    //            connect(shortcut, &QShortcut::activated,
    //                    this, [this]() {
    //                        auto win = getCurrentViewWindow();
    //                        if (win) {
    //                            auto node = win->getBuffer()->getNode();
    //                            if (node) {
    //                                emit Stitch::getInst().locateNodeRequested(node);
    //                            }
    //                        }
    //                    });
    //        }
    //    }

    //    // FocusContentArea.
    //    {
    //        auto shortcut = WidgetUtils::createShortcut(coreConfig.getShortcut(CoreConfig::FocusContentArea), this);
    //        if (shortcut) {
    //            connect(shortcut, &QShortcut::activated,
    //                    this, [this]() {
    //                        auto win = getCurrentViewWindow();
    //                        if (win) {
    //                            win->setFocus();
    //                        } else {
    //                            setFocus();
    //                        }
    //                    });
    //        }
    //    }

    //    // OneSplitLeft.
    //    {
    //        auto shortcut = WidgetUtils::createShortcut(coreConfig.getShortcut(CoreConfig::OneSplitLeft), this);
    //        if (shortcut) {
    //            connect(shortcut, &QShortcut::activated,
    //                    this, [this]() {
    //                        focusSplitByDirection(Direction::Left);
    //                    });
    //        }
    //    }

    //    // OneSplitDown.
    //    {
    //        auto shortcut = WidgetUtils::createShortcut(coreConfig.getShortcut(CoreConfig::OneSplitDown), this);
    //        if (shortcut) {
    //            connect(shortcut, &QShortcut::activated,
    //                    this, [this]() {
    //                        focusSplitByDirection(Direction::Down);
    //                    });
    //        }
    //    }

    //    // OneSplitUp.
    //    {
    //        auto shortcut = WidgetUtils::createShortcut(coreConfig.getShortcut(CoreConfig::OneSplitUp), this);
    //        if (shortcut) {
    //            connect(shortcut, &QShortcut::activated,
    //                    this, [this]() {
    //                        focusSplitByDirection(Direction::Up);
    //                    });
    //        }
    //    }

    //    // OneSplitRight.
    //    {
    //        auto shortcut = WidgetUtils::createShortcut(coreConfig.getShortcut(CoreConfig::OneSplitRight), this);
    //        if (shortcut) {
    //            connect(shortcut, &QShortcut::activated,
    //                    this, [this]() {
    //                        focusSplitByDirection(Direction::Right);
    //                    });
    //        }
    //    }

    // OpenLastClosedFile.
    //    {
    //        auto shortcut = WidgetUtils::createShortcut(coreConfig.getShortcut(CoreConfig::OpenLastClosedFile), this);
    //        if (shortcut) {
    //            connect(shortcut, &QShortcut::activated,
    //                    this, [this]() {
    //                        auto file = HistoryMgr::getInst().popLastClosedFile();
    //                        if (file.m_path.isEmpty()) {
    //                            Stitch::getInst().showStatusMessageShort(tr("No recently closed file"));
    //                            return;
    //                        }
    //                        auto paras = QSharedPointer<FileOpenParameters>::create();
    //                        paras->m_lineNumber = file.m_lineNumber;
    //                        paras->m_mode = file.m_mode;
    //                        paras->m_readOnly = file.m_readOnly;
    //                        emit VNoteX::getInst().openFileRequested(file.m_path, paras);
    //                    });
    //        }
    //    }
}

//bool ViewArea::closeViewWindow(ViewWindow *p_win, bool p_force, bool p_removeSplitIfEmpty)
//{
//    Q_ASSERT(p_win && p_win->getViewSplit());
//    // Make it current ViewWindow.
//    setCurrentViewWindow(p_win);

//    // Get info before close.
//    const auto session = p_win->saveSession();
//    Notebook *notebook = nullptr;
//    if (p_win->getBuffer()) {
//        auto node = p_win->getBuffer()->getNode();
//        if (node) {
//            notebook = node->getNotebook();
//        }
//    }

//    if (!p_win->aboutToClose(p_force)) {
//        return false;
//    }

//    // Update history.
//    updateHistory(session, notebook);

//    // Remove the status widget.
//    if (m_currentStatusWidget && p_win == getCurrentViewWindow()) {
//        Q_ASSERT(m_currentStatusWidget == p_win->statusWidget());
//        emit statusWidgetChanged(nullptr);
//    }

//    auto split = p_win->getViewSplit();
//    split->takeViewWindow(p_win);

//    delete p_win;

//    if (p_removeSplitIfEmpty && split->getViewWindowCount() == 0) {
//        // Remove this split and workspace.
//        removeViewSplit(split, true);
//    }

//    return true;
//}
ViewSplit *ViewArea::getCurrentViewSplit() const
{
    return m_currentSplit;
}

//void ViewArea::setCurrentViewSplit(ViewSplit *p_split, bool p_focus)
//{
//    Q_ASSERT(!p_split || m_splits.contains(p_split));
//    if (p_split == m_currentSplit) {
//        if (p_split && p_focus) {
//            p_split->focus();
//        }
//        return;
//    }

//    if (m_currentSplit) {
//        m_currentSplit->setActive(false);
//    }

//    m_currentSplit = p_split;
//    if (m_currentSplit) {
//        m_currentSplit->setActive(true);
//        if (p_focus) {
//            m_currentSplit->focus();
//        }
//    }
//}
//ViewWindow *ViewArea::getCurrentViewWindow() const
//{
//    auto split = getCurrentViewSplit();
//    if (split) {
//        return split->getCurrentViewWindow();
//    }

//    return nullptr;
//}
